package com.wang.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;

import java.io.IOException;
import java.lang.Exception;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class HttpUtils {

    public static class CommonRsp<T> {
        private int code;
        private String msg;
        private T data;

        public int getCode() {
            return code;
        }

        public void setCode(int code) {
            this.code = code;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

        public T getData() {
            return data;
        }

        public void setData(T data) {
            this.data = data;
        }
    }

    public static class CommonListRsp<T> {
        private int code;
        private String msg;
        private List<T> data;

        public int getCode() {
            return code;
        }

        public void setCode(int code) {
            this.code = code;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

        public List<T> getData() {
            return data;
        }

        public void setData(List<T> data) {
            this.data = data;
        }
    }

    private static final Map<String, String> emptyMap = new HashMap<>();

    public static class NetException extends Exception {
        NetException(String rsp) {
            super(rsp);
        }
    }

    public static OkHttpClient okHttpClient = new OkHttpClient();


    /*************************************************************
     *                              post
     *************************************************************/

    public static <T> List<T> postList(String url, Object body, Class<T> clz) throws IOException, NetException {
        return postList(url, emptyMap, body, clz);
    }

    public static <T> List<T> postList(String url, Map<String, String> header, Object body, Class<T> clz) throws IOException, NetException {
        return parseList(_post(url, header, body));
    }

    public static JSONObject post(String url, Object body) throws IOException, NetException {
        return post(url, emptyMap, body, JSONObject.class);
    }

    public static JSONObject post(String url, Map<String, String> header, Object body) throws IOException, NetException {
        return post(url, header, body, JSONObject.class);
    }

    public static <T> T post(String url, Object body, Class<T> clz) throws IOException, NetException {
        return post(url, emptyMap, body, clz);
    }

    public static <T> T post(String url, Map<String, String> header, Object body, Class<T> clz) throws IOException, NetException {
        return parse(_post(url, header, body));
    }

    /*************************************************************
     *                              get
     *************************************************************/
    public static <T> List<T> getList(String url, Class<T> clz) throws IOException, NetException {
        return getList(url, emptyMap, clz);
    }

    public static <T> List<T> getList(String url, Map<String, String> header, Class<T> clz) throws IOException, NetException {
        return parseList(_get(url, header));
    }

    public static JSONObject get(String url) throws IOException, NetException {
        return get(url, emptyMap, JSONObject.class);
    }

    public static JSONObject get(String url, Map<String, String> header) throws IOException, NetException {
        return get(url, header, JSONObject.class);
    }

    public static <T> T get(String url, Class<T> clz) throws IOException, NetException {
        return get(url, emptyMap, clz);
    }

    public static <T> T get(String url, Map<String, String> header, Class<T> clz) throws IOException, NetException {
        return parse(_get(url, header));
    }

    /*************************************************************
     *                              put
     *************************************************************/
    public static <T> List<T> putList(String url, Object body, Class<T> clz) throws IOException, NetException {
        return putList(url, emptyMap, body, clz);
    }

    public static <T> List<T> putList(String url, Map<String, String> header, Object body, Class<T> clz) throws IOException, NetException {
        return parseList(_put(url, header, body));
    }

    public static JSONObject put(String url, Object body) throws IOException, NetException {
        return put(url, emptyMap, body, JSONObject.class);
    }

    public static JSONObject put(String url, Map<String, String> header, Object body) throws IOException, NetException {
        return put(url, header, body, JSONObject.class);
    }

    public static <T> T put(String url, Object body, Class<T> clz) throws IOException, NetException {
        return put(url, emptyMap, body, clz);
    }

    public static <T> T put(String url, Map<String, String> header, Object body, Class<T> clz) throws IOException, NetException {
        return parse(_put(url, header, body));
    }
    /*************************************************************
     *                              delete
     *************************************************************/
    public static <T> List<T> deleteList(String url, Class<T> clz) throws IOException, NetException {
        return deleteList(url, emptyMap, clz);
    }

    public static <T> List<T> deleteList(String url, Map<String, String> header, Class<T> clz) throws IOException, NetException {
        return parseList(_delete(url, header));
    }

    public static JSONObject delete(String url) throws IOException, NetException {
        return delete(url, emptyMap, JSONObject.class);
    }

    public static JSONObject delete(String url, Map<String, String> header) throws IOException, NetException {
        return delete(url, header, JSONObject.class);
    }

    public static <T> T delete(String url, Class<T> clz) throws IOException, NetException {
        return delete(url, emptyMap, clz);
    }

    public static <T> T delete(String url, Map<String, String> header, Class<T> clz) throws IOException, NetException {
        return parse(_delete(url, header));
    }

    /*************************************************************
     *                              inner
     *************************************************************/
    private static Response _post(String url, Map<String, String> header, Object body) throws IOException {
        String json = JSONObject.toJSONString(body);
        return okHttpClient.newCall((new Request.Builder())
                .url(url)
                .headers(Headers.of(header))
                .post(RequestBody.create(MediaType.get("application/json; charset=utf-8"), json))
                .build()
        ).execute();
    }

    private static Response _put(String url, Map<String, String> header, Object body) throws IOException {
        String json = JSONObject.toJSONString(body);
        return okHttpClient.newCall((new Request.Builder())
                .url(url)
                .headers(Headers.of(header))
                .put(RequestBody.create(MediaType.get("application/json; charset=utf-8"), json))
                .build()
        ).execute();
    }

    private static Response _get(String url, Map<String, String> header) throws IOException {
        return okHttpClient.newCall((new Request.Builder()).url(url).headers(Headers.of(header)).get().build()).execute();
    }

    private static Response _delete(String url, Map<String, String> header) throws IOException {
        return okHttpClient.newCall((new Request.Builder()).url(url).headers(Headers.of(header)).delete().build()).execute();
    }

    private static <T> List<T> parseList(Response response) throws IOException, NetException {
        String rspStr = response.body().string();
        CommonListRsp<T> rsp = JSONObject.parseObject(rspStr, CommonListRsp.class);
        if (rsp.getCode() != 0) throw new NetException(rspStr);
        return rsp.getData();
    }

    private static <T> T parse(Response response) throws IOException, NetException {
        String rspStr = response.body().string();
        CommonRsp<T> rsp = JSONObject.parseObject(rspStr, CommonRsp.class);
        if (rsp.getCode() != 0) throw new NetException(rspStr);
        return rsp.getData();
    }
}